#include <iostream>
#include <string>
#include<list>
#include<unordered_map>

using namespace std;
/**
观察者模式/订阅模式：当一个对象发生改变时，会通知其他对象去处理对象的事件。
*/
class Observer
{
public:
    virtual void handle(int msgid) = 0;
};
class Observer1:public Observer
{
    void handle(int msgid)
    {
        switch (msgid)
        {
        case 1:
            cout << "observer1 recv 1 msg." << endl;
            break;
        case 2:
            cout << "observer1 recv 2 msg." << endl;
            break;
        default:
            cout << "observer1 recv unknow msg." << endl;
            break;
        }
    }
};
class Observer2 : public Observer
{
    void handle(int msgid)
    {
        switch (msgid)
        {
        case 3:
            cout << "observer2 recv 3 msg." << endl;
            break;
        case 2:
            cout << "observer2 recv 2 msg." << endl;
            break;
        default:
            cout << "observer2 recv unknow msg." << endl;
            break;
        }
    }
};
class Observer3 : public Observer
{
    void handle(int msgid)
    {
        switch (msgid)
        {
        case 1:
            cout << "observer3 recv 1 msg." << endl;
            break;
        case 3:
            cout << "observer3 recv 3 msg." << endl;
            break;
        default:
            cout << "observer3 recv unknow msg." << endl;
            break;
        }
    }
};
class Subjects
{
public:
    // 给主题添加观察者对象
    void addObserver(Observer* obser,int msgid)
    {
        // 和下面的操作一致，如果存在msgid为key的情况就直接插入，没有就创建一个并插入
        _submap[msgid].push_back(obser);
        /**
        // 查找map中是否存在有key为msgid的值
        auto it = _submap.find(msgid);
        if(it != _submap.end())
        {
            it->second.push_back(obser);
        }
        else
        {
            list<Observer *> olist;
            olist.push_back(obser);
            _submap.insert(make_pair(msgid, olist));
        }
        */
    }
    // 主题检测发生改变，通知相应的观察者对象处理事件
    void dispatch(int msg)
    {
        auto it = _submap.find(msg);
        if (it != _submap.end())
        {
            for(Observer* pObser:it->second)
            {
                pObser->handle(msg);
            }
        }
    }
private:
    unordered_map<int, list<Observer *>> _submap;
};
int main()
{
    Subjects sub;
    Observer *p1 = new Observer1();
    Observer *p2 = new Observer2();
    Observer *p3 = new Observer3();

    sub.addObserver(p1, 1);
    sub.addObserver(p2, 3);
    sub.addObserver(p3, 1);
    sub.addObserver(p3, 2);
    sub.addObserver(p1, 3);

    sub.dispatch(2);
    
    return 0;
}